using System.Text;
using System.Text.Json;
using hao_Common.Http.Interfaces;
using hao_Common.Http.Options;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace hao_Common.Http.Services
{
    /// <summary>
    /// HTTP请求助手实现
    /// 提供简单易用的HTTP请求方法
    /// </summary>
    public class HttpHelper : IHttpHelper
    {
        private readonly HttpClient _httpClient;
        private readonly ILogger<HttpHelper> _logger;
        private readonly HttpClientOptions _options;
        private readonly JsonSerializerOptions _jsonOptions;

        public HttpHelper(
            HttpClient httpClient,
            ILogger<HttpHelper> logger,
            IOptions<HttpClientOptions> options)
        {
            _httpClient = httpClient;
            _logger = logger;
            _options = options.Value;
            
            // 配置JSON序列化选项
            _jsonOptions = new JsonSerializerOptions
            {
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                WriteIndented = false
            };

            // 设置超时时间
            _httpClient.Timeout = TimeSpan.FromSeconds(_options.TimeoutSeconds);
        }

        /// <summary>
        /// 发送GET请求
        /// </summary>
        public async Task<T?> GetAsync<T>(string url, Dictionary<string, string>? headers = null, CancellationToken cancellationToken = default)
        {
            var response = await SendAsync(HttpMethod.Get, url, null, headers, cancellationToken);
            return await DeserializeResponseAsync<T>(response);
        }

        /// <summary>
        /// 发送GET请求并返回字符串
        /// </summary>
        public async Task<string> GetStringAsync(string url, Dictionary<string, string>? headers = null, CancellationToken cancellationToken = default)
        {
            var response = await SendAsync(HttpMethod.Get, url, null, headers, cancellationToken);
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync(cancellationToken);
        }

        /// <summary>
        /// 发送POST请求
        /// </summary>
        public async Task<T?> PostAsync<T>(string url, object? data = null, Dictionary<string, string>? headers = null, CancellationToken cancellationToken = default)
        {
            var content = CreateJsonContent(data);
            var response = await SendAsync(HttpMethod.Post, url, content, headers, cancellationToken);
            return await DeserializeResponseAsync<T>(response);
        }

        /// <summary>
        /// 发送POST请求并返回字符串
        /// </summary>
        public async Task<string> PostStringAsync(string url, object? data = null, Dictionary<string, string>? headers = null, CancellationToken cancellationToken = default)
        {
            var content = CreateJsonContent(data);
            var response = await SendAsync(HttpMethod.Post, url, content, headers, cancellationToken);
            response.EnsureSuccessStatusCode();
            return await response.Content.ReadAsStringAsync(cancellationToken);
        }

        /// <summary>
        /// 发送PUT请求
        /// </summary>
        public async Task<T?> PutAsync<T>(string url, object? data = null, Dictionary<string, string>? headers = null, CancellationToken cancellationToken = default)
        {
            var content = CreateJsonContent(data);
            var response = await SendAsync(HttpMethod.Put, url, content, headers, cancellationToken);
            return await DeserializeResponseAsync<T>(response);
        }

        /// <summary>
        /// 发送DELETE请求
        /// </summary>
        public async Task<T?> DeleteAsync<T>(string url, Dictionary<string, string>? headers = null, CancellationToken cancellationToken = default)
        {
            var response = await SendAsync(HttpMethod.Delete, url, null, headers, cancellationToken);
            return await DeserializeResponseAsync<T>(response);
        }

        /// <summary>
        /// 发送表单数据POST请求
        /// </summary>
        public async Task<T?> PostFormAsync<T>(string url, Dictionary<string, string> formData, Dictionary<string, string>? headers = null, CancellationToken cancellationToken = default)
        {
            var content = new FormUrlEncodedContent(formData);
            var response = await SendAsync(HttpMethod.Post, url, content, headers, cancellationToken);
            return await DeserializeResponseAsync<T>(response);
        }

        /// <summary>
        /// 上传文件
        /// </summary>
        public async Task<T?> UploadFileAsync<T>(string url, string filePath, string fieldName = "file", Dictionary<string, string>? additionalData = null, Dictionary<string, string>? headers = null, CancellationToken cancellationToken = default)
        {
            if (!File.Exists(filePath))
                throw new FileNotFoundException($"文件不存在: {filePath}");

            using var form = new MultipartFormDataContent();
            
            // 添加文件
            var fileContent = new ByteArrayContent(await File.ReadAllBytesAsync(filePath, cancellationToken));
            fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
            form.Add(fileContent, fieldName, Path.GetFileName(filePath));
            
            // 添加附加数据
            if (additionalData != null)
            {
                foreach (var kvp in additionalData)
                {
                    form.Add(new StringContent(kvp.Value), kvp.Key);
                }
            }

            var response = await SendAsync(HttpMethod.Post, url, form, headers, cancellationToken);
            return await DeserializeResponseAsync<T>(response);
        }

        /// <summary>
        /// 下载文件
        /// </summary>
        public async Task<bool> DownloadFileAsync(string url, string savePath, Dictionary<string, string>? headers = null, CancellationToken cancellationToken = default)
        {
            try
            {
                var response = await SendAsync(HttpMethod.Get, url, null, headers, cancellationToken);
                response.EnsureSuccessStatusCode();
                
                // 确保目录存在
                var directory = Path.GetDirectoryName(savePath);
                if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
                {
                    Directory.CreateDirectory(directory);
                }
                
                // 写入文件
                using var fileStream = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None);
                await response.Content.CopyToAsync(fileStream, cancellationToken);
                
                _logger.LogDebug("文件下载成功: {Url} -> {SavePath}", url, savePath);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "文件下载失败: {Url}", url);
                return false;
            }
        }

        /// <summary>
        /// 发送原始HTTP请求
        /// </summary>
        public async Task<HttpResponseMessage> SendAsync(HttpMethod method, string url, HttpContent? content = null, Dictionary<string, string>? headers = null, CancellationToken cancellationToken = default)
        {
            if (_options.EnableDetailedLogging)
            {
                _logger.LogDebug("发送HTTP请求: {Method} {Url}", method, url);
            }

            try
            {
                using var request = new HttpRequestMessage(method, url)
                {
                    Content = content
                };

                // 添加请求头
                if (headers != null)
                {
                    foreach (var header in headers)
                    {
                        request.Headers.TryAddWithoutValidation(header.Key, header.Value);
                    }
                }

                var response = await _httpClient.SendAsync(request, cancellationToken);
                
                if (_options.EnableDetailedLogging)
                {
                    _logger.LogDebug("HTTP响应: {StatusCode} {ReasonPhrase}", response.StatusCode, response.ReasonPhrase);
                }

                return response;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "HTTP请求失败: {Method} {Url}", method, url);
                throw;
            }
        }

        /// <summary>
        /// 创建JSON内容
        /// </summary>
        private HttpContent? CreateJsonContent(object? data)
        {
            if (data == null) return null;
            
            var json = JsonSerializer.Serialize(data, _jsonOptions);
            return new StringContent(json, Encoding.UTF8, "application/json");
        }

        /// <summary>
        /// 反序列化响应数据
        /// </summary>
        private async Task<T?> DeserializeResponseAsync<T>(HttpResponseMessage response)
        {
            if (!response.IsSuccessStatusCode)
            {
                var errorContent = await response.Content.ReadAsStringAsync();
                _logger.LogError("HTTP请求失败: {StatusCode} {ReasonPhrase} {Content}", 
                    response.StatusCode, response.ReasonPhrase, errorContent);
                
                throw new HttpRequestException($"HTTP请求失败: {response.StatusCode} {response.ReasonPhrase}");
            }

            var content = await response.Content.ReadAsStringAsync();
            
            if (string.IsNullOrEmpty(content))
            {
                return default(T);
            }

            try
            {
                return JsonSerializer.Deserialize<T>(content, _jsonOptions);
            }
            catch (JsonException ex)
            {
                _logger.LogError(ex, "JSON反序列化失败: {Content}", content);
                throw new InvalidOperationException("响应数据格式错误", ex);
            }
        }
    }
}